﻿// ==========================================================================
//  Squidex Headless CMS
// ==========================================================================
//  Copyright (c) Squidex UG (haftungsbeschraenkt)
//  All rights reserved. Licensed under the MIT license.
// ==========================================================================

using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Translations;

namespace Squidex.Domain.Apps.Entities.Contents.DomainObject.Guards;

public static class WorkflowExtensions
{
    public static ValueTask<Status> GetInitialStatusAsync(this ContentOperation operation)
    {
        var workflow = GetWorkflow(operation);

        return workflow.GetInitialStatusAsync(operation.Schema);
    }

    public static ValueTask<bool> ShouldValidateAsync(this ContentOperation operation, Status status)
    {
        var workflow = GetWorkflow(operation);

        return workflow.ShouldValidateAsync(operation.Schema, status);
    }

    public static async Task CheckTransitionAsync(this ContentOperation operation, Status status)
    {
        if (operation.Schema.Type != SchemaType.Singleton)
        {
            var workflow = GetWorkflow(operation);

            if (!await workflow.CanMoveToAsync(operation.Snapshot.ToContent(), operation.Snapshot.EditingStatus, status, operation.User))
            {
                var values = new { oldStatus = operation.Snapshot.EditingStatus, newStatus = status };

                operation.AddError(T.Get("contents.statusTransitionNotAllowed", values), nameof(status));
                operation.ThrowOnErrors();
            }
        }
    }

    public static async Task CheckStatusAsync(this ContentOperation operation, Status status)
    {
        if (operation.Schema.Type != SchemaType.Singleton)
        {
            var workflow = GetWorkflow(operation);

            var statusInfo = await workflow.GetInfoAsync(operation.Snapshot.ToContent(), status);

            if (statusInfo == null)
            {
                operation.AddError(T.Get("contents.statusNotValid"), nameof(status));
                operation.ThrowOnErrors();
            }
        }
    }

    public static async Task CheckUpdateAsync(this ContentOperation operation)
    {
        if (operation.User != null)
        {
            var workflow = GetWorkflow(operation);

            if (!await workflow.CanUpdateAsync(operation.Snapshot.ToContent(), operation.Snapshot.EditingStatus, operation.User))
            {
                throw new DomainException(T.Get("contents.workflowErrorUpdate", new { status = operation.Snapshot.EditingStatus }));
            }
        }
    }

    private static IContentWorkflow GetWorkflow(ContentOperation operation)
    {
        return operation.Resolve<IContentWorkflow>();
    }
}
